home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / lang_c / bc_ti / ti738.asc < prev    next >
Text File  |  1992-02-24  |  38KB  |  991 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.   PRODUCT  :  Borland C++                            NUMBER  :  738
  9.   VERSION  :  All
  10.        OS  :  DOS
  11.      DATE  :  February 25, 1992                       PAGE  :  1/15
  12.  
  13.     TITLE  :  Memory Corruption
  14.  
  15.  
  16.  
  17.  
  18.   POINTERS:
  19.  
  20.   A pointer is a memory location that holds a memory address as its
  21.   contents. When you declare a pointer (e.g. int *foo) the compiler
  22.   will allocate the necessary space to hold the appropriate memory
  23.   address. If the pointer is declared globally the value of its
  24.   address will be 0000 in the case of a near pointer and 0000:0000
  25.   in the case of a far pointer. If the pointer is declared inside a
  26.   function definition as an auto variable (default), then it is
  27.   created on the stack and will have a default address of whatever
  28.   value happened to be at that location on the stack when it is
  29.   created. In either case these default memory addresses are
  30.   invalid. This is referred to as an uninitialized pointer and
  31.   should never be dereferenced. To initialize a pointer you must
  32.   either dynamically allocate memory using malloc, farmalloc,
  33.   calloc, farcalloc, realloc, farrealloc, allocmem or new (C++
  34.   only) or you can associate the pointer with a variable who's
  35.   memory is allocated by the compiler at compile time (e.g. int
  36.   foo[100]). Once the pointer has been initialized it is then safe
  37.   to dereference the pointer using the * operator.
  38.  
  39.        int *p;   OK  Uninitialized pointer
  40.        *p = 4;   WRONG This puts a value of 4 at whatever
  41.                  address happened to be stored where *p was
  42.                  created.
  43.        int  i;   OK  Statically declared variable. Static meaning
  44.                  the memory is allocated by the compiler at
  45.                  compile time.
  46.  
  47.        p = &i;   OK  Associating p with a statically declared
  48.                  variable.
  49.        p = (int *) malloc(2); OK  Associating p with dynamically
  50.                  allocated memory. The parameter could also have
  51.                  been sizeof(int).
  52.  
  53.   Modifying the variable p (e.g. p = 0;) will make the memory
  54.   address that p holds equal to 0. When modifying dereferenced p,
  55.   denoted by *p, the value stored at the memory address p holds as
  56.   its value is modified.
  57.  
  58.        *p = 4;   OK  p still holds the address that malloc
  59.                  returned above, but that address in memory
  60.                  now holds a value of 4.
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.  
  74.   PRODUCT  :  Borland C++                            NUMBER  :  738
  75.   VERSION  :  All
  76.        OS  :  DOS
  77.      DATE  :  February 25, 1992                       PAGE  :  2/15
  78.  
  79.     TITLE  :  Memory Corruption
  80.  
  81.  
  82.  
  83.  
  84.        p = 4;    OK  *p now points to offset 4 from DS. It is
  85.                  important to note that this type of assignment
  86.                  should only be made if the address (4 in this
  87.                  case) is valid. Otherwise memory corruption
  88.                  will occur. Also note that if a far memory
  89.                  model (see Memory Models) is used the segment
  90.                  may not be DS, but will be whatever its initial
  91.                  value was.
  92.  
  93.   There are 3 types of pointers. They are near, far, and huge.
  94.  
  95.   Near pointers have a size of 2 bytes. They only store the offset
  96.   of the address the pointer is referencing. An address consisting
  97.   of only an offset has a range of 0 - 64K bytes starting from the
  98.   beginning of DGROUP. A near pointer can be incremented and
  99.   decremented using arithmetic operators (+, -, ++, and --) through
  100.   the entire address range. Any attempt to increment a near pointer
  101.   that has a value of 64K (0xffff) will result in a value of 0.
  102.   This is referred to as wrapping the pointer. A corresponding
  103.   result can be expected when attempting to decrement a pointer
  104.   that contains an address of 0, except the result will be 64K
  105.   instead of 0. In addition to being incremented and decremented,
  106.   near pointers can be compared to one another using relational
  107.   operators ( <, >, ==, >= and <= ).
  108.  
  109.   Far pointers have a size of 4 bytes. They store both the segment
  110.   and the offset of the address the pointer is referencing. A far
  111.   pointer has an address range of 0 - 1M bytes. It is important to
  112.   understand that an addressing range of 1M does not remove the
  113.   640K barrier from the program. It means that the pointer can
  114.   address the upper memory area (641 - 1M) which typically contains
  115.   video memory, ROM and anything else that may be loaded high. A
  116.   far pointer can be incremented and decremented using arithmetic
  117.   operators. When a far pointer is incremented or decremented ONLY
  118.   the offset of the pointer is actually incremented or decremented.
  119.   The segment is never incremented by the arithmetic operators.
  120.   This means that although a far pointer can address up to 1Mb of
  121.   memory, it can only be incremented through 64Kb and the offset
  122.   will start at zero again without changing the value of the
  123.   segment. This is referred to as "wrapping" the pointer (e.g.
  124.   0F3E:FFFF + 1 = 0F3E:0000). When a far pointer is decremented
  125.   from zero it will wrap the other way and become 64K. Far pointers
  126.   are not unique. It is possible to have two far memory addresses
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136.  
  137.  
  138.  
  139.  
  140.   PRODUCT  :  Borland C++                            NUMBER  :  738
  141.   VERSION  :  All
  142.        OS  :  DOS
  143.      DATE  :  February 25, 1992                       PAGE  :  3/15
  144.  
  145.     TITLE  :  Memory Corruption
  146.  
  147.  
  148.  
  149.  
  150.   that have different segment values and different offset values
  151.   that address the same memory location e.g. 0777:2222 has an
  152.   absolute address of 07770 + 2222 = 09992 and 0999:0002 has an
  153.   absolute address of 09990 + 0002 = 09992. When relational
  154.   operators are used on far pointers only the offsets are compared.
  155.   For example: if we let a = 0777:2222 and let b = 0999:0002 then a
  156.   == b would return false because this is equivalent to 2222 ==
  157.   0002 which is in fact false. In other words relational operators
  158.   will only work on far pointers if the segment values of the
  159.   pointers being compared are the same.
  160.  
  161.   Huge pointers have a size of 4 bytes. They store both the segment
  162.   and the offset of the address the pointer is referencing. A huge
  163.   pointer has an address range of 0 - 1M bytes. A huge pointer can
  164.   be incremented and decremented using arithmetic operators. The
  165.   only difference between a far pointer and a huge pointer is that
  166.   a huge pointer is normalized by the compiler. A normalized
  167.   pointer is one that has as much of the address as possible in the
  168.   segment, meaning that the offset is never larger than 15. A huge
  169.   pointer is normalized only when pointer arithmetic is performed
  170.   on it. It is not normalized when an assignment is made. You can
  171.   cause it to be normalized without changing the value by
  172.   incrementing and then decrementing it. The offset must be less
  173.   than 16 because the segment can represent any value greater than
  174.   or equal to 16 (e.g. Absolute address 0x17 in a normalized form
  175.   would be 0001:0001. While a far pointer could address the
  176.   absolute address 0x17 with 0000:0017, this is not a valid huge
  177.   (normalized) pointer because the offset is greater than 0000F.).
  178.   Huge pointers can also be incremented and decremented using
  179.   arithmetic operators, but since they are normalized they will not
  180.   wrap like far pointers. Huge pointers can be reliably used with
  181.   relational operators because they are normalized. This works
  182.   because normalization of huge pointers insures that every huge
  183.   pointer is unique. It is important to understand that huge
  184.   pointers are never the default pointer, even in the huge memory
  185.   model.
  186.  
  187.   MEMORY MODELS:
  188.  
  189.   The important difference between the memory models are the size
  190.   of the data and code pointers, number of data and code segments
  191.   and the number and type of heaps available. For our purposes we
  192.   will refer to the tiny, small and medium memory models as near
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.  
  201.  
  202.  
  203.  
  204.  
  205.  
  206.   PRODUCT  :  Borland C++                            NUMBER  :  738
  207.   VERSION  :  All
  208.        OS  :  DOS
  209.      DATE  :  February 25, 1992                       PAGE  :  4/15
  210.  
  211.     TITLE  :  Memory Corruption
  212.  
  213.  
  214.  
  215.  
  216.   memory models and the compact, large and huge as far memory
  217.   models. We use this notation because the near memory models have
  218.   both a near and far heap while the far memory models have only a
  219.   far heap. The near memory models do not have a separate stack
  220.   segment like the far memory models do. This is because the data
  221.   segment, the near heap and the stack are all part of DGROUP
  222.   meaning that the total size of these things must be less than or
  223.   equal to 64K bytes. The tiny model is an exception to this in
  224.   that it also includes the code segment and psp (256 bytes) in
  225.   DGROUP also.
  226.  
  227.                                TINY  SML   MED   CMP  LRG  HUGE
  228.  
  229.        Near Heap             : Yes   Yes   Yes   No   No   No
  230.        Far Heap              : Yes   Yes   Yes   Yes  Yes  Yes
  231.        Code pointers         : near  near  far   near far  far
  232.        Data pointers         : near  near  near  far  far  far
  233.        Separate stack segment: No    No    No    Yes  Yes  Yes
  234.        Multiple code segments: No    No    Yes   No   Yes  Yes
  235.        Multiple data segments: No    No    No    No   No   Yes
  236.  
  237.   The near and far heap fields above indicate whether or not those
  238.   heaps exist in the specified memory model. If a memory model is
  239.   used that doesn't contain a near heap and one or more of the near
  240.   heap functions i.e. malloc, free, heapwalk etc. are used, they
  241.   are mapped by the compiler into a special far version of the call
  242.   that will allocate the memory off the correct heap (far). All of
  243.   the parameters of these special near memory allocation functions
  244.   are the same, but the pointer returned by this special version of
  245.   the near memory allocation function will be a far pointer rather
  246.   than a near pointer. The code and data pointer fields show the
  247.   default pointer size for each memory model. It is important to
  248.   note that none of the memory models use huge pointers by default.
  249.   These defaults can all be overridden using the modifiers near,
  250.   far or huge (e.g. int far *foo;  or void near goo();). The
  251.   separate stack segment field indicates whether the stack is part
  252.   of DGROUP or in its own segment. Multiple code and data segments
  253.   indicate if the specified memory model can have more than one of
  254.   each type. If more than one of either type is allowed the
  255.   segments are divided based on their corresponding source files
  256.   e.g. a 3 source file program in the huge memory model would have
  257.   3 code segments and 3 data segments where the code and global
  258.  
  259.  
  260.  
  261.  
  262.  
  263.  
  264.  
  265.  
  266.  
  267.  
  268.  
  269.  
  270.  
  271.  
  272.   PRODUCT  :  Borland C++                            NUMBER  :  738
  273.   VERSION  :  All
  274.        OS  :  DOS
  275.      DATE  :  February 25, 1992                       PAGE  :  5/15
  276.  
  277.     TITLE  :  Memory Corruption
  278.  
  279.  
  280.  
  281.  
  282.   data declared in each source file would go into the corresponding
  283.   segment.
  284.  
  285.   HEAP:
  286.  
  287.   The global variable _heaplen only applies to the near heap. It is
  288.   used to specify the size of the heap. If no value is specified
  289.   for _heaplen then DGROUP will default to 64K bytes. If a value is
  290.   specified then the size of DGROUP will be computed by summing the
  291.   size of everything in DGROUP and then adding the size of _heaplen
  292.   and _stklen. The global variable _stklen is used to specify how
  293.   much memory to set aside for the stack.
  294.  
  295.   The near heap, when present, begins just after the global data
  296.   and grows up toward the stack (higher memory) and the stack is
  297.   situated at the end of DGROUP and grows down toward the heap
  298.   (lower memory). The empty space separating the near heap and the
  299.   stack can be used by either the heap or the stack regardless of
  300.   whether it was reserved using _heaplen or _stklen variables. It
  301.   is possible to dynamically allocate memory that is actually being
  302.   used by the stack without generating a warning or an error. This
  303.   is a common cause of memory corruption and can be avoided by
  304.   using coreleft to keep track of the available memory to insure it
  305.   is available prior to allocating it.
  306.  
  307.   The far heap exists just above the stack in memory. The far
  308.   heap's initial size is zero. When the program processes a request
  309.   for memory from the far heap it requests DOS to reallocate the
  310.   current program size (minimum of 16 byte chunks) to include the
  311.   requested size. DOS maintains its own heap very similar to the
  312.   heap used by a program. Each block of memory that DOS allocates
  313.   has a header called a memory control block (MCB) which is used to
  314.   manage the heap used by DOS. When there is 1K bytes of free
  315.   memory at the top of the far heap the program again calls DOS to
  316.   reallocate the program space giving the memory back to DOS. All
  317.   pointers used to reference the far heap should be either far or
  318.   huge since the far heap is in a separate segment. It is important
  319.   to note that if another process requests memory from DOS and the
  320.   memory is available then that other program will get the next
  321.   free block DOS owns which is the one immediately following the
  322.   far heap in memory. This means that the next time your program
  323.   attempts to reallocate the current program size the DOS allocate
  324.   function will fail because your program has now been blocked in
  325.  
  326.  
  327.  
  328.  
  329.  
  330.  
  331.  
  332.  
  333.  
  334.  
  335.  
  336.  
  337.  
  338.   PRODUCT  :  Borland C++                            NUMBER  :  738
  339.   VERSION  :  All
  340.        OS  :  DOS
  341.      DATE  :  February 25, 1992                       PAGE  :  6/15
  342.  
  343.     TITLE  :  Memory Corruption
  344.  
  345.  
  346.  
  347.  
  348.   by a DOS memory control block (MCB) other than your program MCB.
  349.   This is also the case if allocmem is called from within your
  350.   program.
  351.  
  352.   STACK:
  353.  
  354.   Stack checking is an option that can be turned on or off that
  355.   will check to see if the stack has overflowed. When this option
  356.   is turned on the compiler will generate code that will check,
  357.   upon entering a new function, to insure there is adequate room on
  358.   the stack to make the call. If there isn't room the appropriate
  359.   error message will be generated and the program will exit. The
  360.   checking is done in the near memory models by comparing __brklvl
  361.   that marks the end of the near heap and SP which marks the actual
  362.   top of the stack. In the far memory models this checking is done
  363.   by comparing SP which marks the actual top of the stack and
  364.   _stklen which is the size of the stack segment. Stack checking is
  365.   not fool proof. The Run Time Library (RTL) of functions found in
  366.   the Library Reference Manual were not compiled with stack
  367.   checking turned on. This means there is a possibility of
  368.   overflowing the stack when making a call to an RTL function even
  369.   though stack checking is turned on. Functions that use a stack
  370.   other than the program stack should not use the stack checking
  371.   option (e.g asynchronous interrupt service routines).
  372.  
  373.   When floating point is turned on in any memory model the floating
  374.   point emulator information is located in the first 416 bytes of
  375.   the physical stack (SS:0000 - SS::415). This information must be
  376.   transferred if you are trying to switch stacks. Receiving false
  377.   floating point error messages is a good indication that something
  378.   may be corrupting this portion of the stack.
  379.  
  380.   The size of the stack is determined by the startup code at run
  381.   time. If a link map is generated you will see a size specified
  382.   for the stack that may be different than the size you specified.
  383.   This value you see in the link map is a value that DOS is told,
  384.   but the actual size requirement is met at runtime.
  385.  
  386.   In the near memory models the stack exists within the 64K byte
  387.   limit defined by DGROUP which also contains global data and the
  388.   near heap. In the tiny memory model it also contains the code
  389.   segment. In the near memory when the stack overflows the first
  390.   thing corrupted is the near heap followed by the global data.
  391.  
  392.  
  393.  
  394.  
  395.  
  396.  
  397.  
  398.  
  399.  
  400.  
  401.  
  402.  
  403.  
  404.   PRODUCT  :  Borland C++                            NUMBER  :  738
  405.   VERSION  :  All
  406.        OS  :  DOS
  407.      DATE  :  February 25, 1992                       PAGE  :  7/15
  408.  
  409.     TITLE  :  Memory Corruption
  410.  
  411.  
  412.  
  413.  
  414.   In the far memory models the stack exists immediately following
  415.   the data segment and is just before the far heap. In the far
  416.   memory models the first thing that is corrupted when the stack
  417.   overflows is the floating point emulator followed by the far
  418.   heap.
  419.  
  420.   In order to avoid stack overflow it is important to understand
  421.   what makes up the stack. In the far memory model only, the
  422.   emulator occupies the 416 bytes from SS:0000 to SS:0415 located
  423.   at the top of the logical stack. As each function is entered
  424.   space is allocated for all its parameters. They are created on
  425.   the stack from right to left followed by the return address.
  426.   Space is then allocated for all auto (default for local
  427.   variables) variables in the order of declaration. All this space
  428.   remains allocated until the function returns to the calling
  429.   function. In other words if you then called another function, the
  430.   space allocated for the first function would remain allocated
  431.   until the first function regained control and then returned
  432.   control to its calling function.  In the case of C++ programs,
  433.   all class copies used by the compiler are implicitly created on
  434.   the stack unless a copy constructor is provided that uses the
  435.   alternative of dynamic memory allocation.
  436.  
  437.   COMMON PROBLEMS LEADING TO MEMORY CORRUPTION:
  438.  
  439.   Using an uninitialized pointer is probably the most common cause
  440.   of memory corruption. It is possible to use an uninitialized
  441.   pointer and have a program work. It just depends on what the
  442.   default address is when the pointer is created and if anything
  443.   else is attempting to use that address.
  444.  
  445.   Failure to include ALLOC.H is a common mistake. When ALLOC.H is
  446.   left out the type checking is not performed. Since there is no
  447.   prototype the memory allocation functions are all thought by the
  448.   compiler to be returning integer types. A program will usually
  449.   continue to work without ALLOC.H in the near memory models, since
  450.   an integer is the same size as the near pointers used in these
  451.   memory models. However in the far memory models the segment half
  452.   of the pointer is lost when the memory allocation function
  453.   attempts to return a far pointer. These programs may or may not
  454.   work. You should always include ALLOC.H.
  455.  
  456.  
  457.  
  458.  
  459.  
  460.  
  461.  
  462.  
  463.  
  464.  
  465.  
  466.  
  467.  
  468.  
  469.  
  470.   PRODUCT  :  Borland C++                            NUMBER  :  738
  471.   VERSION  :  All
  472.        OS  :  DOS
  473.      DATE  :  February 25, 1992                       PAGE  :  8/15
  474.  
  475.     TITLE  :  Memory Corruption
  476.  
  477.  
  478.  
  479.  
  480.   Failure to check the return value from a memory allocation call
  481.   can result in a NULL pointer. Technically a NULL pointer is
  482.   defined as an invalid pointer. In more practical use, however, a
  483.   NULL pointer is interpreted as meaning a pointer that holds 0 as
  484.   its address (e.g. p = 0;). NULL for our purposes will mean a
  485.   pointer that holds an address of 0. A memory allocation function
  486.   can fail and return NULL if there is no memory left, if the
  487.   program was unable to resize its MCB or if there is some sort of
  488.   heap corruption (whether it be in the DOS heap or your program
  489.   heap). Your code should always check to insure the pointer
  490.   returned by a memory allocation function is not NULL.
  491.  
  492.   Stack overflow is a common problem. When making a function call
  493.   the stack can overflow and corrupt some other variables and
  494.   return without the user being the wiser. A later attempt to use
  495.   the corrupted variable can result in incorrect program results or
  496.   hanging the system.
  497.  
  498.   Indexing out of bounds occurs with both statically declared
  499.   arrays and dynamically declared arrays. An array declared as char
  500.   foo[100] has a valid index range of 0 - 99. Making an assignment
  501.   to foo[100] is memory corruption since foo[100] does not belong
  502.   to the array foo. A non-huge array will wrap if a value larger
  503.   than unsigned (0xffff) is used to index it.
  504.  
  505.   The largest dynamically allocated array that can be addressed
  506.   using a far pointer is 65531 bytes because the offset returned by
  507.   farmalloc will always have an offset of 0004. This offset is
  508.   guaranteed because the far heap is paragraph aligned. The missing
  509.   4 bytes are used by the program heap manager as a block header to
  510.   manage the heap. Of course a far pointer has the potential to
  511.   rival the power available with the huge pointers if the user does
  512.   the necessary normalizing of the pointer.
  513.  
  514.   In a far memory model, a call to a near memory function will be
  515.   mapped into the corresponding special function call described
  516.   above in the heap section. In the near memory models all pointers
  517.   declared are near by default and should not be used with any of
  518.   the far memory allocation functions i.e. farmalloc and farcalloc.
  519.   The compiler will generate a warning about a suspicious pointer
  520.   conversion but it won't prevent it from happening. The first time
  521.   such a pointer is used it will address an offset of 0004 in the
  522.   DGROUP. Also be aware of the memory model that the program is
  523.  
  524.  
  525.  
  526.  
  527.  
  528.  
  529.  
  530.  
  531.  
  532.  
  533.  
  534.  
  535.  
  536.   PRODUCT  :  Borland C++                            NUMBER  :  738
  537.   VERSION  :  All
  538.        OS  :  DOS
  539.      DATE  :  February 25, 1992                       PAGE  :  9/15
  540.  
  541.     TITLE  :  Memory Corruption
  542.  
  543.  
  544.  
  545.  
  546.   compiled in. If it is one of the far memory models then all calls
  547.   to the near memory allocation functions will be mapped into the
  548.   corresponding far functions behind the scenes by the compiler. In
  549.   some cases this also changes the parameter and return types. It
  550.   is strongly suggested that if you are using a far memory model
  551.   you use only the far memory allocation functions to avoid
  552.   confusion at a later date and make debugging easier.
  553.  
  554.   The duration of a variable is very important. A global pointer
  555.   should never reference a local auto variable, because when that
  556.   local variable goes out of scope its memory is released to be
  557.   reused by the stack for something else. If the global pointer is
  558.   later used it may be erroneously referencing something else.
  559.  
  560.   Receiving the message "Null pointer assignment" after your
  561.   program has completed its run is usually caused by the use of an
  562.   uninitialized pointer. You can track the cause of this message
  563.   down by placing the two watches ( (char *)4,s and *(char *) 0,4m
  564.   ) on your program. The first 47 bytes of the data segment are not
  565.   valid addresses for any variables in your program. When your
  566.   program exits these 47 bytes are checked to see if they have been
  567.   modified. If they have the warning message is printed on your
  568.   screen. These two watches will allow you to monitor the beginning
  569.   of the data segment to identify the offending line of code.
  570.  
  571.   The memory allocation functions used to free dynamically
  572.   allocated memory (free, farfree, delete) should only be used on
  573.   pointers that hold an address returned by a dynamic memory
  574.   allocation function i.e. farmalloc, malloc, new etc.. Any attempt
  575.   to free an array declared as int foo[100] will result in
  576.   undefined results possibly corrupting memory. The memory freeing
  577.   functions should never be called twice with the same address as a
  578.   parameter unless that same address has been reallocated since the
  579.   last memory free function call. The results are undefined and can
  580.   produce memory corruption.
  581.  
  582.   One very common problem is character arrays that are not NULL
  583.   terminated. Every character array must be terminated by a NULL or
  584.   0 i.e.
  585.    char foo[100];
  586.    foo[0] = 0; This is a NULL terminated "empty" string
  587.  
  588.  
  589.  
  590.  
  591.  
  592.  
  593.  
  594.  
  595.  
  596.  
  597.  
  598.  
  599.  
  600.  
  601.  
  602.   PRODUCT  :  Borland C++                            NUMBER  :  738
  603.   VERSION  :  All
  604.        OS  :  DOS
  605.      DATE  :  February 25, 1992                      PAGE  :  10/15
  606.  
  607.     TITLE  :  Memory Corruption
  608.  
  609.  
  610.  
  611.  
  612.    foo[10] = '\0';This is a NULL terminated string with 10
  613.                   undefined characters preceding the NULL.
  614.    Remember indexing starts at 0 not 1.
  615.  
  616.    foo[0] = '0';  Incorrect this is not a NULL terminated
  617.                   string.
  618.  
  619.   All of the functions that are listed in string.h found in the
  620.   include directory rely on this NULL termination. The NULL is what
  621.   they use to tell them they have reached the end of the string and
  622.   should stop processing the string. If the NULL is missing then
  623.   these functions will continue on processing possibly corrupting
  624.   memory as they go. For most of the string family of functions
  625.   list in string.h you will see a corresponding n family of
  626.   functions i.e. strcpy and strncpy, stricmp and strnicmp, strcat
  627.   and strncat etc.. The corresponding n functions perform the same
  628.   tasks as their corresponding counter parts with the exception
  629.   that they take an extra parameter n which specifies how many
  630.   characters in the string to operate on. These n functions will be
  631.   finished when they have processed the string up to the NULL
  632.   character or until they have processed n characters in the
  633.   string. It is strongly recommended that these n family of
  634.   functions be used rather than their counterparts because if they
  635.   do receive a string that is not NULL terminated they will stop
  636.   after they have processed n characters rather than continuing on
  637.   and corrupting memory. You will also see an _f family of
  638.   functions in string.h that have corresponding standard and n
  639.   family of functions i.e. strcat and _fstrcat; strchr and
  640.   _fstrchr; strncmp and _fstrncmp etc.. The _f family of functions
  641.   is not limited to the string family of functions and will be
  642.   addressed later.
  643.  
  644.   In general most functions that work with pointers have a
  645.   corresponding _f family of functions. The _f family of functions
  646.   were designed for use exclusively in the small and medium memory
  647.   models because they are the only memory models that have both a
  648.   near and a far heap. The _f family of functions are designed for
  649.   use with far pointers in the small and medium memory models. They
  650.   are not necessary in the far memory models because those RTL
  651.   functions have already been compiled using the default far
  652.   pointers as parameter and return types. Near pointers present no
  653.   special problems in the far memory models because they can be
  654.   implicitly converted by the compiler.
  655.  
  656.  
  657.  
  658.  
  659.  
  660.  
  661.  
  662.  
  663.  
  664.  
  665.  
  666.  
  667.  
  668.   PRODUCT  :  Borland C++                            NUMBER  :  738
  669.   VERSION  :  All
  670.        OS  :  DOS
  671.      DATE  :  February 25, 1992                      PAGE  :  11/15
  672.  
  673.     TITLE  :  Memory Corruption
  674.  
  675.  
  676.  
  677.  
  678.   The C++ language presents some special problems due to
  679.   constructors and destructors which are called by the compiler
  680.   automatically. The first rule is that for every constructor call
  681.   there must be a corresponding destructor call. If no dynamic
  682.   memory allocation and deallocation is taking place in these
  683.   constructors and destructors one may not even notice if the
  684.   destructor gets called twice, but if it is, the heap will most
  685.   likely become corrupted. One can check for violations of this
  686.   property by placing simple print statements or breakpoints (if
  687.   using a debugger) in each of the constructors and destructors and
  688.   check for compliance.
  689.  
  690.   The stack size variable should never be set larger than 0xffe0.
  691.   The startup code will increase this value to 0xfff0 as part of
  692.   the process to make the stack paragraph aligned. If _stklen is
  693.   set to a value greater than 0xffef then the value of stklen will
  694.   become 0 in the startup code causing all stack checking to fail.
  695.  
  696.   If dynamic memory allocation is used in a constructor in C++ then
  697.   a copy constructor is almost always required. A copy constructor
  698.   is a constructor that will dynamically allocate the needed memory
  699.   and then copy what is stored in the corresponding memory in the
  700.   class instance being copied. The compiler will often times need
  701.   to generate temporaries of the class instances e.g. when an
  702.   instance is being passed as a parameter. If a copy constructor is
  703.   not defined it will use the default memberwise copy resulting in
  704.   two different pointers in two different class instances pointing
  705.   to the same dynamically allocated memory. This means that when
  706.   the first instance is destructed the memory addressed by its
  707.   pointer is freed leaving the remaining instance of the class with
  708.   an invalid pointer that, if used, will cause memory corruption.
  709.   If a copy constructor is defined the compiler will use it versus
  710.   the default copy constructor.
  711.  
  712.   DEBUGGING TIPS AND TECHNIQUES:
  713.  
  714.   Once you are sure that the problem is not one of the common
  715.   mistakes listed above you roll up your sleeves and prepare for a
  716.   real debugging session. The real trick to debugging is to
  717.   understand how memory works and how a program is structured in
  718.   that memory. If you understand these things then you can use
  719.   things like different size pointers and different segment
  720.   organization to debug your program. Switching memory models makes
  721.  
  722.  
  723.  
  724.  
  725.  
  726.  
  727.  
  728.  
  729.  
  730.  
  731.  
  732.  
  733.  
  734.   PRODUCT  :  Borland C++                            NUMBER  :  738
  735.   VERSION  :  All
  736.        OS  :  DOS
  737.      DATE  :  February 25, 1992                      PAGE  :  12/15
  738.  
  739.     TITLE  :  Memory Corruption
  740.  
  741.  
  742.  
  743.  
  744.   all these things happen. The hard part is knowing which one to
  745.   switch to and what to look for when you get there. In some cases
  746.   you may not be able switch memory models due to program
  747.   constraints and may be forced to use other techniques. When none
  748.   of the simpler tricks such as changing memory models works, then
  749.   the divide and conquer technique should be used. The divide and
  750.   conquer method is the most reliable method, but it is often the
  751.   most difficult to implement.
  752.  
  753.   A good technique to employ in your programming is to initialize
  754.   all pointers to NULL when they are declared and again after they
  755.   have been freed. This way all invalid pointers will contain the
  756.   same address and can be tested prior to use and prior to being
  757.   freed.
  758.  
  759.   All compiler warnings should be turned on. It is important to
  760.   note that the compiler isn't shipped with all the warnings turned
  761.   on. Inside the IDE you have to turn each warning on explicitly
  762.   and on the command line you should give the -w+ option. You can
  763.   find more information about how to turn these on in the User's
  764.   Guide.
  765.  
  766.   In a near memory model the stack and the near heap grow towards
  767.   each other in memory. It is possible for either one to overstep
  768.   its bounds and corrupt the other. This condition is easy to test
  769.   for by moving to a far memory model and then increase the stack
  770.   size to 0xffe0. If the program then behaves differently this is a
  771.   strong indication that one or the other of these conditions
  772.   existed. If this is the case, there are two possible solutions.
  773.   The first is to use the far memory allocation functions and the
  774.   second is to stay in the far memory model and adjust the stack
  775.   size as necessary.
  776.  
  777.   In the far memory models the stack exists directly below the far
  778.   heap in memory. As the stack grows the stack pointer SP
  779.   approaches zero. When the stack overflows SP jumps from 0 to
  780.   0xffffh. If the stack has been declared to be 0xffe0 then the
  781.   beginning of the logical stack will be corrupted else the far
  782.   heap at a point exactly 64k higher in memory from SS will be
  783.   corrupted. Note if you are using floating point the emulator
  784.   located on the top of the logical stack will become corrupted
  785.   before SP even wraps. This could result in a program running OK,
  786.   but giving incorrect results from computations or aborting the
  787.  
  788.  
  789.  
  790.  
  791.  
  792.  
  793.  
  794.  
  795.  
  796.  
  797.  
  798.  
  799.  
  800.   PRODUCT  :  Borland C++                            NUMBER  :  738
  801.   VERSION  :  All
  802.        OS  :  DOS
  803.      DATE  :  February 25, 1992                      PAGE  :  13/15
  804.  
  805.     TITLE  :  Memory Corruption
  806.  
  807.  
  808.  
  809.  
  810.   program. The stack size can be increased to oxffe0 by the line
  811.   "extern unsigned _stklen = 0xffe0u;" at file scope (outside any
  812.   function definition) inside any source file being linked into
  813.   your program.
  814.  
  815.   A common mistake in writing an overloaded operator is to allocate
  816.   a new instance of a class, calculate the new value of this
  817.   instance, and return the pointer to this new instance. This will
  818.   work, but the compiler has no way of knowing that it should free
  819.   up the new data after it has finished with it. A program may work
  820.   "perfectly" on small amounts of data, but crash after it has
  821.   exhausted most of the available memory. This is called a "memory
  822.   leak." Overloading NEW and DELETE to keep a log of used/freed
  823.   memory will assist in tracking these leaks.
  824.  
  825.   When debugging a live program, it is easy to display and verify
  826.   an integer, string or other simple data structure. Verification
  827.   of more complex structures may involve several layers of pointer
  828.   indirection. It may be tedious to examine all elements in a
  829.   linked list for example. If you write functions to check your
  830.   structures/classes, these can be called within your program at
  831.   debug time. For instances of classes, these should be virtual
  832.   member functions, so that the correct routine is called for
  833.   instances of derived classes accessed through base class
  834.   pointers. Call these functions at the start and end of all other
  835.   member functions to flag corrupted data and assist in isolating
  836.   problems.
  837.  
  838.   The divide and conquer method is implemented by manipulating the
  839.   different components composing the program. These components will
  840.   most likely be single functions or groups of functions that lend
  841.   themselves to being individually tested by a driver program.
  842.  
  843.   A driver program is a small program used to test a particular
  844.   module or group of modules. It should set up the environment and
  845.   pass the parameters required by the function being tested.
  846.   Sometimes it may be more desirable to test an entire program
  847.   without a particular function.
  848.  
  849.   This can be done by using a stub. A stub is a testing function
  850.   designed to take the same parameters and return the same type as
  851.   the function it is replacing. Once the offending function has
  852.  
  853.  
  854.  
  855.  
  856.  
  857.  
  858.  
  859.  
  860.  
  861.  
  862.  
  863.  
  864.  
  865.  
  866.   PRODUCT  :  Borland C++                            NUMBER  :  738
  867.   VERSION  :  All
  868.        OS  :  DOS
  869.      DATE  :  February 25, 1992                      PAGE  :  14/15
  870.  
  871.     TITLE  :  Memory Corruption
  872.  
  873.  
  874.  
  875.  
  876.   been located the offending line of code must be located by
  877.   commenting out and changing various lines within the function.
  878.  
  879.   When you have identified what you suspect as being the offending
  880.   line of code you need to confirm this. This is done by writing a
  881.   separated test program to test the line of code all by itself. If
  882.   it still doesn't work correctly then you have found the problem.
  883.   If it works in the example program then you have most likely
  884.   found a side effect caused by something else that must be
  885.   identified. For instance something else may modify the value of a
  886.   pointer that, when used by the suspect code, causes the machine
  887.   to hang. Enough information should be obtained from the code
  888.   producing the side effect to give you a new place to look. In our
  889.   example we would watch the address of the pointer that got
  890.   corrupted by using Turbo Debugger and setting a hardware
  891.   breakpoint on the address of the pointer that would stop program
  892.   execution whenever the pointer value is modified. It is rare that
  893.   an identified problem needs more than 20 lines of code to
  894.   reproduce.
  895.  
  896.   Once you feel that you have isolated it you should ask yourself
  897.   whether every piece of code in your example is necessary to
  898.   reproduce the problem. For instance if the problem requires a
  899.   structure to manifest itself then what the structure contains is
  900.   probably not important. The divide portion of the algorithm is
  901.   usually the most difficult and the most time consuming.
  902.  
  903.   Now the you have located the problem you can usually determine
  904.   what the cause was. If you know what the cause of the problem was
  905.   you should be able to summarize the problem in a few sentences.
  906.   If you cannot do this you probably don't have a complete grasp of
  907.   the problem. Borland Technical Support will be able to provide
  908.   you with the best support when you have the problem isolated and
  909.   have reproduced it in an small example, whether you are just
  910.   letting us know the problem is there or you're not sure what is
  911.   causing the problem.
  912.  
  913.   A function familiar to C programmers is the assert() macro. This
  914.   function is well suited for C++ programming. Assert() takes an
  915.   expression as a parameter, and if the expression is false,
  916.   usually halts the program and prints a message giving the line
  917.   number and file where the problem occurred. At any point where an
  918.   important assumption is made about the correctness of calculated
  919.  
  920.  
  921.  
  922.  
  923.  
  924.  
  925.  
  926.  
  927.  
  928.  
  929.  
  930.  
  931.  
  932.   PRODUCT  :  Borland C++                            NUMBER  :  738
  933.   VERSION  :  All
  934.        OS  :  DOS
  935.      DATE  :  February 25, 1992                      PAGE  :  15/15
  936.  
  937.     TITLE  :  Memory Corruption
  938.  
  939.  
  940.  
  941.  
  942.   data, insert an assert() call, which will display a message if
  943.   the assumption is invalid. For example, the default for a switch
  944.   statement is an ideal place to insert an assert() call. Insure
  945.   that you include ASSERT.H. Defining the symbol "NDEBUG" will
  946.   cause the compiler to ignore (i.e. not generate code for) all
  947.   assert() calls. This way the source code will not have to be
  948.   modified to remove the excess debugging code.
  949.  
  950.  
  951.  
  952.  
  953.  
  954.  
  955.  
  956.  
  957.  
  958.  
  959.  
  960.  
  961.  
  962.  
  963.  
  964.  
  965.  
  966.  
  967.  
  968.  
  969.  
  970.  
  971.  
  972.  
  973.  
  974.  
  975.  
  976.  
  977.  
  978.  
  979.  
  980.  
  981.  
  982.  
  983.  
  984.  
  985.  
  986.  
  987.  
  988.  
  989.  
  990.  
  991.